/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package poproject.OptimizationTask;

import java.util.ArrayList;

/**
 * Reprezentuje trasę wytyczoną na mapie.
 * 
 * @author Eruanno
 */
public class MapTrack {
   
    /**
     * Model mapy, do której należy ta trasa.
     */
    private MapModel mapModel;
    
    /**
     * Tablica z koordynatami definiującymi trasę.
     */
    private int[] trackLevels;
    
    /**
     * Tworzy egzemplarz trasy.
     * @param mapModel Mapa do której należy trasa.
     */
    public MapTrack(MapModel mapModel) {
        this.mapModel = mapModel;
        trackLevels = new int[mapModel.numOfAreas()+1];
    }
    
    /**
     * Ustawia poziom wierzchołka trasy na danej pozycji.
     * @param position
     * @param level 
     */
    public void setTrackPoint(int position, int level) {
        
        trackLevels[position] = level;
    }
    
    /**
     * Zwraca poziom wierzchołka trasy na danej pozycji.
     * @param position
     * @return 
     */
    public int trackPoint(int position) {
        
        return trackLevels[position];
    }
    
    /**
     * Zwraca koszt budowy trasy. Może być liczony różnymi metodami w zależności
     * od sposobu liczenia długości trasy.
     * @return Koszt budowy trasy.
     */
    public double calculateCost(CostType costType) {
        switch(costType) {
            case Optimized:
                return calculateOptimizedCost();
            case Real:
                return calculateRealCost();
            default:
                throw new UnsupportedOperationException("Nie wspierany rodzaj kosztów.");
        }
    }

    private double calculateOptimizedCost() {
        ArrayList<Integer> costs = mapModel.areaCosts();
        
        int accum = 0;
        for(int i = 0; i < costs.size(); i++)
        {
            int dx = (trackLevels[i+1] - trackLevels[i]);
            accum += costs.get(i) * dx * dx;
        }
        
        return accum;
    }

    private double calculateRealCost() {
        ArrayList<Integer> costs = mapModel.areaCosts();
        
        int accum = 0;
        for(int i = 0; i < costs.size(); i++)
        {
            int dx = (trackLevels[i+1] - trackLevels[i]);
            double distance = Math.sqrt(1 + dx*dx);
            accum += costs.get(i) * distance;
        }
        
        return accum;
    }
    
    /**
     * Sposób liczenia kosztu wybudowania drogi
     */
    public enum CostType {
        Optimized,      ///< Koszt liczony jest tak jak we wskaźniku minimalizacji
        Real            ///< Koszt rzeczywisty uwzględniający drogę euklidesową
    }
}
